/*                          UX-Framework                               
 *                                                                 
 *  iZE Co.,Ltd. Copyright 2009 All rights reserved.          
 *  This file is distributed under the terms of the GNU Lesser 
 *  General Public License, described in file LICENSE.                                     
 */
package jp.ize.ux;

// {{{ imports
#if flash9
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.events.FocusEvent;
#elseif flash
#end

import jp.ize.ux.UXFocusManager;
import jp.ize.ux.geom.UXSize;
import jp.ize.ux.utils.UXSizeHint;
import jp.ize.ux.events.UXKeyboardEvent;
import jp.ize.iwp.RuntimeEngine;

// }}}
// {{{ class UXObject extends UXSprite
/** 
 * UXObjectクラス.<br>
 * UX-Frameworkの基礎となるクラス。基礎的な描画プロパティ、コンテナ機能、テーマ機能、フォーカス機能、
 * イベント機能などを持ちます。<br>
 *
 * @author		iZE Co., Ltd.<br>
 * @version		$Id: UXObject.hx 160 2009-05-01 06:19:45Z tocy.net $<br>
 */
class UXObject extends UXSprite
{
	// {{{ properties
	// {{{ public var focusManager : UXFocusManager;
	/**
	 * フォーカスマネージャを格納します
	 */
	public var focusManager : UXFocusManager;
	// }}}
	// {{{ public var name(default, default) : String
	/**
	 * このコンポーネントの名前です。主にユーザーのアクティビティを観察・保存する際にコンポーネントの識別子として用いられます。
	 */
	public var uxname(default, default) : String;
	// }}}
	// {{{ public var followMatrix(default, null) : Bool;	
	/**
	 * オブジェクトの大きさに拡大率を追従させるかどうかを示します。デフォルトでfalseです。
	 */
	public var followMatrix(default, null) : Bool;
	//}}}
	// {{{ public var layoutSize(default, default) : UXSize;
	/**
	 * レイアウト領域を示します。nullの場合はこのオブジェクトのwidth, height情報で表されるサイズがレイアウト領域になります。
	 */
	public var layoutSize(default, default) : UXSize;
	//}}}
	// {{{ public var sizeHint(default, default) : UXSizeHint
	/**
	 * このコンポーネントがレイアウトクラスによって配置される時に、このコンポーネントの大きさを制御する情報です。
	 * 詳細はUXSizeHintクラスを参照してください。
	 */
	public var sizeHint(default, default) : UXSizeHint;
	// }}}
	// {{{ public var focusIndex(default, default) : Int
	/**
	 * フォーカスが移動する順番を規定する数値。絶対値に意味は無く、UXFocusManagerの同一インスタンスに登録されているUXObject同士のfocusIndexの大小が意味を持ちます。
	 */
	public var focusIndex(default, default) : Int;
	// }}}	
	// {{{ public var selected(default, default) : Bool
	/**
	 * 選択状態かどうかを保持します。利用しない場合は false です。デフォルトも false です。
	 */
	public var selected(default, default) : Bool;
	// }}}	
	// }}}
	// {{{ public function new()
	/**
	 * コンストラクタ
	 */
	public function new()
	{
		super();
		focusRect    = null;
		followMatrix = false;
		selected     = false;
		var me = this;
		addEventListener( FocusEvent.FOCUS_IN, function(fe){
			me.gotFocus();
		}, false, 0, true );
		addEventListener( FocusEvent.FOCUS_OUT, function(fe){
			me.lostFocus();
		}, false, 0, true );
	}
	// }}}
	// {{{ public function addUXChild( c:UXObject ) : Void
	/**
	 * 子要素を追加します。
	 */
	public function addUXChild( c:UXObject ) : Void
	{
		addChild( c );
	}

	// }}}
	// {{{ public function removeUXChild( c:UXObject ) : Void
	/**
	 * 子要素を削除します。
	 */
	public function removeUXChild( c:UXObject ) : Void
	{
		removeChildren( c );
		removeChild( c );
	}

	// }}}
	// {{{ public function removeChildren( c:DisplayObjectContainer ) : Void
	/**
	 * すべての子要素を削除します。
	 */
	public function removeChildren( c:DisplayObjectContainer ) : Void
	{
		var i = c.numChildren - 1;
		while ( i>=0 ) {
			var cc = c.getChildAt(i);
			if ( Std.is(cc,DisplayObjectContainer) ) {
				removeChildren(cast(cc,DisplayObjectContainer));
			}
			c.removeChild(cc);
			cc = null;
			i--;
		}
	}

	// }}}
	// {{{ public function addUXEventListener( e:Dynamic, f:Dynamic->Void ) : Void
	/**
	* イベントリスナーを追加します。
	*/
	public function addUXEventListener( e:Dynamic, f:Dynamic->Void ) : Void
	{
		if ( e==UXKeyboardEvent.KEY_DOWN || e==UXKeyboardEvent.KEY_UP ) {
			RuntimeEngine.getStage().addEventListener( e, f, false, 0, true );
		} else {
			addEventListener( e, f, false, 0, true );
		}
	}

	// }}}
	// {{{ public function removeUXEventListener( e:Dynamic, f:Dynamic->Void ) : Void
	/**
	* イベントリスナーを削除します。
	*/
	public function removeUXEventListener( e:Dynamic, f:Dynamic->Void ) : Void
	{
		removeEventListener( e, f );
	}

	// }}}
	// {{{ public function putEvent( event : Event ) : Bool
	/**
	 * 指定されたイベントをこのオブジェクトに配信します。
	 */
	public function putEvent( event : Event ) : Bool
	{
		return true;
	}
	// }}}
	// {{{ public function setFocusManager( m : UXFocusManager ) : Void
	/**
	 * このオブジェクトのフォーカスを管理するマネージャーを得ます。フォーカス関連の操作を行う前に、この関数を呼び出しておく必要があります。
	 */
	public function setFocusManager( m : UXFocusManager ) : Void
	{
		focusManager = m;
	}
	// }}}
	// {{{ public function focus() : Void
	/**
	 * このオブジェクトにフォーカスを当てます。このオブジェクトがUXFocusMangerのインスタンスを持っていなければ、何もしません。
	 */
	public function focus() : Void
	{
		if ( focusManager!=null ) {
			//focusManager.setFocusIndex( focusIndex );
			focusManager.focusIndex = focusIndex;
		}
	}
	// }}}
	// {{{ public function getFocusee() : Dynamic
	/**
	 * このオブジェクトからフォーカス用のオブジェクトを取得します。
	 */
	public function getFocusee() : Dynamic
	{
		return this;
	}
	// }}}
	// {{{ public function gotFocus() : Void
	/**
	* フォーカスを得たときに呼出されるメソッドです。
	*/
	public function gotFocus() : Void
	{
		focus();
	}

	// }}}
	// {{{ public function lostFocus() : Void
	/**
	* フォーカスを失ったときに呼出されるメソッドです。
	*/
	public function lostFocus() : Void
	{
		if ( focusManager!=null ) {
			//focusManager.focusIndex = focusIndex;
		}
	}

	// }}}
	#if flash9
	// {{{ private function onKeyFocusChange( e : FocusEvent ) : Void
	/**
	 * フォーカスがキーボードイベントによって移動する前に呼ばれるイベントです。
	 * フォーカスマネージャーからのイベントは特別に素通し、通常のイベントはフォーカスマネージャーに転送します。
	 */
	private function onKeyFocusChange( e : FocusEvent ) : Void
	{
		/* UXFocusEventにはhintフィールドがあるはず */
		var hint : String = Reflect.field(e, "hint");
		if( hint != null ) {
			/* 素通し */
		} else {
			/* 通常のFocusEventだと判断. */
			e.preventDefault (); /* フォーカスの移動を止めます. */
			if( focusManager != null) {
				/* フォーカスマネージャーに依頼します. */
				if( e.shiftKey ) {
					focusManager.previous(); 
				} else {
					focusManager.next();
				}
			}
		}
	}
	// }}}
	// {{{ public function onMouseFocusChange( e : FocusEvent ) : Void
	/**
	 * フォーカスがマウスイベントによって移動する前に呼ばれるイベントです。
	 * フォーカスマネージャーからのイベントは特別に素通し、通常のイベントはフォーカスマネージャーに転送します。
	 */
	public function onMouseFocusChange( e : FocusEvent ) : Void
	{
		/* UXFocusEventにはhintフィールドがあるはず */
		var hint : String = Reflect.field(e, "hint");
		if( hint != null ) {
			/* 素通し */
		} else {
			/* 通常のFocusEventだと判断. */
			e.preventDefault (); /* フォーカスの移動を止めます. */
			if( focusManager != null) {
				/* フォーカスマネージャーに依頼します. */
				var obj : UXObject = Reflect.field( e.relatedObject, "xxobj" );
				if( obj != null ) {
					focusManager.setFocus( obj );
				}
			}
		}
	}
	// }}}
	#end
}
// }}}
